/**********************************************************************
 *<
	FILE: XMLUtility.cpp

	DESCRIPTION:	Handy functions for XML, to keep the code a bit cleaner

	CREATED BY:		Neil Hazzard

	HISTORY:		Summer 2002

 *>	Copyright (c) 2002, All Rights Reserved.
 **********************************************************************/

#include "IGameExporter.h"
#include "atlbase.h"
#include "msxml2.h"

bool InitialiseXML(IXMLDOMNode  ** root, IXMLDOMDocument ** doc)
{

	HRESULT hr;
	hr = CoInitialize(NULL); 
	// Check the return value, hr...
	hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,  IID_IXMLDOMDocument, (void**)&doc);
	if(FAILED(hr))
		return false;
	// Check the return value, hr...
//	hr = (IXMLDOMDocument &)doc->QueryInterface(IID_IXMLDOMNode, (void **)&root);
	if(FAILED(hr))
		return false;

	return true;
	
}


bool CreateXMLNode(IXMLDOMDocument * doc, IXMLDOMNode * node, TCHAR *nodeName, IXMLDOMNode ** newNode)
{

	IXMLDOMNode * sceneNode;
	doc->createNode(CComVariant(NODE_ELEMENT), CComBSTR(nodeName), NULL, &sceneNode);
	node->appendChild(sceneNode,newNode);
	return true;
}

bool AddXMLAttribute(IXMLDOMNode * node, TCHAR * name, TCHAR * value)
{
	CComQIPtr<IXMLDOMElement> element;
	element = node;
	element->setAttribute(CComBSTR(name), CComVariant(value));
	return true;
}

bool AddXMLText(IXMLDOMDocument * doc, IXMLDOMNode * node, TCHAR * text)
{
	CComPtr <IXMLDOMText> keydata = NULL;
	doc->createTextNode(CComBSTR(text), &keydata);
	node->appendChild(keydata,NULL);
	return true;

}
IXMLDOMText* CreateXMLText(IXMLDOMDocument* doc, IXMLDOMNode* parentNode, TCHAR* name)
{
	CComPtr<IXMLDOMNode> node;
	IXMLDOMText* textNode = NULL;

	if( CreateXMLNode(doc,parentNode, name,&node) == true) {
		doc->createTextNode(CComBSTR(""), &textNode);
		node->appendChild(textNode,NULL);
	}

	return textNode;
}

void PrettyPrint(const TCHAR* name, IXMLDOMDocument* pXMLDoc)
{
	// perform formatting XSLT transform to get indented XML output
	IXMLDOMDocument* pXSLDoc;
	BSTR outputXML;
	HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,  IID_IXMLDOMDocument, (void**)&pXSLDoc);
	if (SUCCEEDED(hr)) {
		// load indenting XSL doc 
		VARIANT_BOOL result;
		CComBSTR indentXSL(
			"<xsl:stylesheet version=\"1.0\""
			"      xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
			"   <xsl:output method=\"xml\"/>"
			"   <xsl:param name=\"indent-increment\" select=\"'\t'\" />"
			"   <xsl:template match=\"node()\">"
			"      <xsl:param name=\"indent\" select=\"'&#xA;'\"/>"
			"      <xsl:value-of select=\"$indent\"/>"
			"      <xsl:copy>"
			"        <xsl:copy-of select=\"@*\" />"
			"        <xsl:apply-templates>"
			"          <xsl:with-param name=\"indent\""
			"               select=\"concat($indent, $indent-increment)\"/>"
			"        </xsl:apply-templates>"
			"        <xsl:if test=\"node()\">"
			"          <xsl:value-of select=\"$indent\"/>"
			"        </xsl:if>"
			"      </xsl:copy>"
			"   </xsl:template>"
//			"   <xsl:template match=\"comment()|processing-instruction()\">"
//			"      <xsl:copy />"
//			"   </xsl:template>"
//			"   <!-- WARNING: this is dangerous. Handle with care -->"
//			"   <xsl:template match=\"text()[normalize-space(.)='']\"/>"
			"</xsl:stylesheet>"
			);
		hr = pXSLDoc->loadXML(indentXSL, &result);
		if (SUCCEEDED(hr)) {
			// perform transform
			hr = pXMLDoc->transformNode(pXSLDoc, &outputXML);
		}
	}

	// output transformed XML if previous sequence succeeded, else normal XMLDoc save
	if (SUCCEEDED(hr)) {
		FILE* out = _tfopen(name, _T("w"));
		if (out != NULL) {
			// hack the UTF-16 back to UTF-8 (there probably is a way to mod the stylesheet to do this)
			wchar_t* enc = wcsstr(outputXML, L"\"UTF-16\"");
			if (enc != NULL) memcpy(enc, L"\"utf-8\" ", 8 * sizeof(wchar_t));
			// convert BSTR to MBCS for output
			int len = WideCharToMultiByte(CP_ACP, 0, outputXML, -1, 0, 0, NULL, NULL);
			TCHAR* buf = (TCHAR*)malloc(len * sizeof(WCHAR));
			WideCharToMultiByte(CP_ACP, 0, outputXML, -1, buf, len, NULL, NULL);
			// write the XML
			_fputts(buf, out);   
			fclose(out);
			free(buf);
		}
		SysFreeString(outputXML);
	}
	else
		// save the XML graph out to the export file
		pXMLDoc->save(CComVariant(name));
}
